#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    
    FileTotalSize=0;    //数据总大小
    FileSendedSize=0;   //已经发送的大小
    FileRemainedSize=FileTotalSize;    //剩下的数据大小
    loadSize=4*1024;          //每次发送的大小


    ui->pushButton_disconnect->setEnabled(false);
    ui->pushButton_send->setEnabled(false);

    ui->pushButton_sendFile->setEnabled(false);
    ui->pushButton_chooseFile->setEnabled(false);
    ui->plainTextEdit_messageShow->setReadOnly(true);
    

    setFixedSize(this->width(),this->height());
    setWindowFlags(windowFlags()&~Qt::WindowMaximizeButtonHint);

    socketText=new QTcpSocket(this);
    socketFile=new QTcpSocket(this);

    connect(socketText,&QTcpSocket::readyRead,this,&Widget::OnReadyReadFunc);  //当有信息可以读取时，触发读取槽函数

    connect(socketText,&QTcpSocket::disconnected,this,&Widget::OnDisconnectedFunc);

    connect(socketFile,&QTcpSocket::bytesWritten,this,&Widget::UpdateProgressFunc);   //当有数据时及时更新
    setSheet();          //设置样式
    GetLocalIPAdress();  //将地址填写在窗口label上
#include<QDebug>
    QFile file("://new//prefix1//styles.qss");
    if(file.open(QFile::ReadOnly|QFile::Text))
    {
        qDebug()<<123<<endl;
        QTextStream in(&file);
        setStyleSheet(in.readAll());
        file.close();

    }

}

Widget::~Widget()
{
    delete ui;
}

void Widget::GetLocalIPAdress()    //获取本地ip，并在窗口显示
{
    QString strName=QHostInfo::localHostName();
    QHostInfo info=QHostInfo::fromName(strName);

    QList<QHostAddress>addrlist=info.addresses();
    QString localaddr;

    for(auto addr :addrlist)
    {
        if(addr.protocol()==QAbstractSocket::IPv4Protocol&& addr != QHostAddress::LocalHost)
        {
            localaddr=addr.toString();
            break;
        }
    }
    if (!localaddr.isEmpty())
    {
         ui->label_localaddr->setText(" 地址: "+localaddr);
    }
    else
    {
         ui->label_localaddr->setText("未找到合适的 IPv4 地址");
    }
}

//连接断开服务两个按钮的槽函数实现
void Widget::on_pushButton_connect_clicked()      //连接服务器
{

    if(socketText)
    {
        QString addr= ui->lineEdit->text();


        quint16 port=ui->spinBox->value();

        ui->plainTextEdit_messageShow->appendPlainText("[******正在尝试连接服务器******]");

        socketText->connectToHost(QHostAddress(addr),port);
        socketFile->connectToHost(QHostAddress(addr),port);

        if(socketText->waitForConnected(10000)) //1秒内没有连接断开
        {

            ui->plainTextEdit_messageShow->appendPlainText("[*****成功连接到服务器*****]");

            ui->pushButton_connect->setEnabled(false);
            ui->pushButton_disconnect->setEnabled(true);
            ui->pushButton_send->setEnabled(true);

            ui->pushButton_chooseFile->setEnabled(true);
        }
        else
        {
            ui->plainTextEdit_messageShow->appendPlainText("[*****连接服务器超时*****]");
        }

    }
    else
    {
        ui->plainTextEdit_messageShow->appendPlainText("套接字未正确初始化");
        return;
    }

}

void Widget::on_pushButton_disconnect_clicked()   //断开连接服务器
{
    if(socketText->state()==QAbstractSocket::ConnectedState)
        socketText->disconnectFromHost();   //这个会触发断开连接的槽函数
}

//三个按钮的槽函数实现
void Widget::on_pushButton_exit_clicked()       //退出系统
{
    socketFile->close();
    socketText->close();
    close();
}

void Widget::on_pushButton_clear_clicked()      //清除屏幕信息
{
    ui->plainTextEdit_messageShow->clear();
}

void Widget::on_pushButton_send_clicked()       //发送信息
{
    QString message=ui->plainTextEdit_messageSend->toPlainText();
    QByteArray data=message.toUtf8();

    if(socketText)
    {
        socketText->write(data);
        if(socketText->waitForBytesWritten())  //waitForBytesWritten 方法等待数据写入完成，并检查其返回值来判断发送是否成功
        {
            QString strtmp=QDateTime::currentDateTime().toString("yyyy/MM/dd hh:mm:ss");
            ui->plainTextEdit_messageShow->appendPlainText(strtmp+" 向服务器发送信息: "+message);
            ui->plainTextEdit_messageSend->clear();
            ui->plainTextEdit_messageSend->setFocus();
        }
        else
        {
            ui->plainTextEdit_messageShow->appendPlainText(tr("%1 数据发送失败").arg(socketText->errorString()));
        }

    }
    else
    {
        ui->plainTextEdit_messageShow->appendPlainText(tr("套接字未连接，无法发送数据"));
    }
}

//发送文件的两个按钮实现
void Widget::on_pushButton_chooseFile_clicked()       //选择文件
{
    FileName=QFileDialog::getOpenFileName(this,"请选择要传输的文件");

    FileTotalSize = QFileInfo(FileName).size();
    FileSendedSize = 0;
    FileRemainedSize = FileTotalSize;

    if(!FileName.isEmpty())
    {
        ui->plainTextEdit_messageShow->appendPlainText(QString("客户打开文件为: %1 成功").arg(FileName));
        ui->pushButton_sendFile->setEnabled(true);
    }
    else
    {
        QMessageBox::information(this,"tip","请选择一个文件");
        return;
    }
}

void Widget::on_pushButton_sendFile_clicked()       //发送文件
{

    QString strtmp=QDateTime::currentDateTime().toString("yyyy/MM/dd hh:mm:ss");

    localFile=new QFile(FileName);

    if(!localFile->open(QFile::ReadOnly))
    {
        QMessageBox::information(this,"tip","打开文件错误,请检查！");
        return;
    }

    FileTotalSize=localFile->size();      //要发送的文件大小

    QDataStream out(&OutBlocks,QIODevice::WriteOnly);
    QString currentName=FileName.right(FileName.size()-FileName.lastIndexOf('/') -1);  //提取出filename.txt 这种格式


    out<<qint64(0)<<qint64(0)<<currentName;    //依次写入文件总大小，文件名大小，文件名

    FileTotalSize+=OutBlocks.size();           //总大小是文件名大小等信息和实际文件名的总和

    out.device()->seek(0);                    //回到out初始位置填写空缺的

    out<<FileTotalSize<<qint64(OutBlocks.size()-sizeof(qint64)*2);

    //得到除了头文件的剩余部分大小
    FileRemainedSize= FileTotalSize - socketFile->write(OutBlocks);

    OutBlocks.resize(0);

    ui->plainTextEdit_messageShow->appendPlainText(strtmp+currentName+" 头部发送成功");

}

void Widget::UpdateProgressFunc(qint64 numBytes)      //更新进度条
{
    QString strTime=QDateTime::currentDateTime().toString();
    //确认已发送的信息大小
    FileSendedSize=FileSendedSize +(int)numBytes;

    if(FileRemainedSize>0)  //剩下数据大小
    {
        //从文件读取数据发送到缓冲区，每次发送文件大小4kb
        //如果剩下的数据不足4kb，就发送剩下大小
        OutBlocks=localFile->read(qMin(FileRemainedSize,loadSize));

        //从发送缓冲区发送数据，计算发送完一次数据还剩下多少
        FileRemainedSize=FileRemainedSize- (int)socketFile->write(OutBlocks);

        //清空缓冲区
        OutBlocks.resize(0);
    }
    else
    {
        localFile->close();   //没有数据，关闭文件
    }

    //进度条的更新
    ui->progressBar->setMaximum(FileTotalSize);
    ui->progressBar->setValue(FileSendedSize);

    if(FileSendedSize==FileTotalSize)
    {
        ui->plainTextEdit_messageShow->appendPlainText(strTime+" 文件已经成功传输到服务器 ");
        localFile->close();
    }

}
//文本相关的槽函数
void Widget::OnDisconnectedFunc()             //断开连接
{
    ui->pushButton_connect->setEnabled(true);

    ui->pushButton_disconnect->setEnabled(false);
    ui->pushButton_send->setEnabled(false);
    ui->pushButton_chooseFile->setEnabled(false);

    ui->plainTextEdit_messageShow->appendPlainText("[*****已断开与服务器的连接*****]");
}

void Widget::OnReadyReadFunc()                //信息读取
{
    if(socketText->bytesAvailable()&&socketText)
    {
        QString strTime=QDateTime::currentDateTime().toString("yyyy/MM/dd hh:mm:ss");

        QByteArray readText=socketText->readAll();
        QString strText=QString::fromUtf8(readText);
        ui->plainTextEdit_messageShow->appendPlainText(strTime+" 收到服务器消息: "+readText);

    }
}

void Widget::DisplayErrorFunc(QAbstractSocket::SocketError)    //显示错误
{

}

void Widget::setSheet()                       //设置样式
{
    QPalette palate1=ui->label_addr->palette();
    palate1.setColor(QPalette::WindowText,Qt::yellow);
    ui->label_addr->setPalette(palate1);

    QPalette palate2=ui->label_port->palette();
    palate2.setColor(QPalette::WindowText,Qt::yellow);
    ui->label_port->setPalette(palate2);

    QPalette palate3=ui->groupBox_messagesend->palette();
    palate3.setColor(QPalette::WindowText,Qt::yellow);
    ui->groupBox_messagesend->setPalette(palate3);

    QPalette palate4=ui->groupBox_messageshow->palette();
    palate4.setColor(QPalette::WindowText,Qt::yellow);
    ui->groupBox_messageshow->setPalette(palate4);

    QPalette palate5=ui->label_file->palette();
    palate5.setColor(QPalette::WindowText,Qt::yellow);
    ui->label_file->setPalette(palate5);

    QPalette palate6=ui->label_localaddr->palette();
    palate6.setColor(QPalette::WindowText,Qt::yellow);
    ui->label_localaddr->setPalette(palate6);

    QFont font1=ui->label_addr->font();
    font1.setBold(true);
    ui->label_addr->setFont(font1);

    QFont font2=ui->label_port->font();
    font2.setBold(true);
    ui->label_port->setFont(font2);

    //文本框设为透明
    ui->plainTextEdit_messageSend->setStyleSheet("background-color: rgba(255, 255, 255, 0.4);");
    ui->plainTextEdit_messageShow->setStyleSheet("background-color: rgba(255, 255, 255, 0.4);");

}

//虚函数
void Widget::closeEvent(QCloseEvent *event)    //窗口的关闭
{
    if(socketText->state()==QAbstractSocket::ConnectedState)
    {
        socketText->disconnectFromHost();
    }
    if(socketFile->state()==QAbstractSocket::ConnectedState)
    {
        socketFile->disconnectFromHost();
    }
    if(socketText)
    {
        socketText->close();
        socketText=nullptr;
    }
    if(socketFile)
    {
        socketFile->close();

        socketFile=nullptr;
    }

    event->accept();
}

void Widget::paintEvent(QPaintEvent *)         //窗口背景
{
    QPainter painter(this);
    painter.drawPixmap(rect(),QPixmap(":/new/prefix1/images/background.png"),QRect());
}




//
